/*CMATIX - Originally a standalone class, now part of RoboFo (SDIE)
CMATIX, or ColorMatrix is a class/system for searching a screen or select area of a screen for a matrix of pixels.
Written by Bradley Galloway
Copyright Notice: CMATIX (c) Bradley Galloway - 2012 */

/*Error Notice
May throw error when being debugged, due to not following Microsoft's standards.*/

#pragma once
#include <Windows.h>
typedef struct{
        long x;
        long y;
} TPOINT;

typedef long tpixel;

class CMATIX{
public: static tpixel *ToPixelArray(int members, ...){
        __asm{
                mov eax, members
                shl eax, 2
                push eax
                call malloc
                add esp, 4
                cmp eax, 0
                jne _passerror
                mov eax, 0
                jmp jret
_passerror:
                mov edi, eax
                mov ecx, members
                lea esi, [ebp+0xC]
loopx:
                mov edx, [esi]
                mov [edi], edx
                add edi, 4
                add esi, 4
                dec ecx
                jnz loopx
jret:
        }
}
public: static bool TestMatrix(tpixel *pPixelMatrix, unsigned long ulWidth, unsigned long ulHeight,unsigned long ulX, unsigned long ulY, RGBQUAD *pPixelData, RECT *prctSearchArea){
        for(unsigned long ulMatrixX = 0; ulMatrixX<ulWidth;ulMatrixX++)
                for(unsigned long ulMatrixY = 0; ulMatrixY<ulHeight; ulMatrixY++)
                       if(((*(tpixel*)(&pPixelData[((prctSearchArea->bottom-ulY-1)*prctSearchArea->right)+ulX]))&0x00FFFFFF)!=pPixelMatrix[(ulWidth*ulMatrixY)+ulMatrixX])return false;
        return true;
}
public: static tpixel *GetScreenPixelData(RECT *prctArea){
        tpixel *pPixelData = new tpixel[(prctArea->right - prctArea->left) * (prctArea->bottom -prctArea->top)];
        BITMAPINFO BMPINFO = {0};
        BMPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        BMPINFO.bmiHeader.biWidth = (prctArea->right - prctArea->left);
        BMPINFO.bmiHeader.biHeight = (prctArea->bottom - prctArea->top);
        BMPINFO.bmiHeader.biPlanes = 1;
        BMPINFO.bmiHeader.biBitCount = 32;
        BMPINFO.bmiHeader.biCompression = BI_RGB;
		HWND desktophwnd = GetDesktopWindow();
        HDC hdcSource = GetDC(desktophwnd);
        HDC hdcDestination = CreateCompatibleDC(hdcSource);
        HBITMAP hBMP = CreateCompatibleBitmap(hdcSource, (prctArea->right - prctArea->left),(prctArea->bottom - prctArea->top));
        SelectObject(hdcDestination,hBMP);
    BitBlt(hdcDestination,0,0,(prctArea->right - prctArea->left),(prctArea->bottom - prctArea->top), hdcSource,0,0,SRCCOPY); // depending on winapi version, add '| 0x40000000', usually for newer versions.
        GetDIBits(hdcDestination, hBMP, 0, (prctArea->bottom - prctArea->top), pPixelData, &BMPINFO, DIB_RGB_COLORS);
//        ReleaseDC(desktophwnd, hdcSource);
        DeleteDC(hdcDestination);
        DeleteObject(hBMP);
        //delete[] (void*)&BMPINFO;
        return pPixelData;
}
public: static tpixel *GetWindowPixelData(HWND hWindow, RECT *prctArea, bool brelease = false){
        tpixel *pPixelData = new tpixel[(prctArea->right - prctArea->left) * (prctArea->bottom -prctArea->top)];
        BITMAPINFO BMPINFO = {0};
        BMPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        BMPINFO.bmiHeader.biWidth = (prctArea->right - prctArea->left);
        BMPINFO.bmiHeader.biHeight = (prctArea->bottom - prctArea->top);
        BMPINFO.bmiHeader.biPlanes = 1;
        BMPINFO.bmiHeader.biBitCount = 32;
        BMPINFO.bmiHeader.biCompression = BI_RGB;
        HDC hdcSource = GetDC(hWindow);
        HDC hdcDestination = CreateCompatibleDC(hdcSource);
        HBITMAP hBMP = CreateCompatibleBitmap(hdcSource, (prctArea->right - prctArea->left),(prctArea->bottom - prctArea->top));
        SelectObject(hdcDestination,hBMP);
    BitBlt(hdcDestination,0,0,(prctArea->right - prctArea->left),(prctArea->bottom - prctArea->top), hdcSource,0,0,SRCCOPY); // depending on winapi version, add '| 0x40000000', usually for newer versions.
        GetDIBits(hdcDestination, hBMP, 0, (prctArea->bottom - prctArea->top), pPixelData, &BMPINFO, DIB_RGB_COLORS);
        if(brelease) ReleaseDC(hWindow, hdcSource);
        DeleteDC(hdcDestination);
        DeleteObject(hBMP);
        //delete[] (void*)&BMPINFO;
        return pPixelData;
}
public: static TPOINT ConstructPoint(unsigned long x, unsigned long y){
                        TPOINT ptRet = {x, y};
                        return ptRet;
                }
public: static TPOINT LocateMatrix(tpixel *pPixelMatrix, unsigned long ulWidth, unsigned long ulHeight, RECT *prctSearchArea, RGBQUAD *pPixelData){
        if(!(ulWidth%2 || ulHeight%2)) return ConstructPoint(-1, -1);
        for(unsigned long ulX = prctSearchArea->left + ((ulWidth-1)/2);ulX< (prctSearchArea->right -((ulWidth-1)/2));ulX++)
                for(unsigned long ulY = prctSearchArea->top + ((ulHeight-1)/2); ulY<(prctSearchArea->bottom - ((ulHeight-1)/2));ulY++){
                        if(TestMatrix(pPixelMatrix, ulWidth, ulHeight, ulX, ulY, pPixelData, prctSearchArea))return ConstructPoint(ulX+((ulWidth-1)/2), ulY+((ulHeight-1)/2));
                }
        }
};